package com.huo.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import com.huo.common.enumtype.R;
import com.huo.filestransport.vo.FtpFileInfo;
import com.huo.filestransport.vo.FtpServerInfo;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
@Service
public class SftpUtil {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private FtpServerInfo ftpServerInfo;

	/**
	 * 获取ftp连接
	 * 
	 * @return
	 */
	public ChannelSftp getFTPConnection() {
		logger.info("FtpUtil-->connect--ftp连接开始>>>>>>host=" + ftpServerInfo.getIp() + ">>>port" + ftpServerInfo.getPort() + ">>>username=" + ftpServerInfo.getUsername());  
		ChannelSftp sftp = null;
		JSch jsch = new JSch();  
	        try {  
	            jsch.getSession(ftpServerInfo.getUsername(), ftpServerInfo.getIp(), ftpServerInfo.getPort());  
	            Session sshSession = jsch.getSession(ftpServerInfo.getUsername(), ftpServerInfo.getIp(), ftpServerInfo.getPort());
	            logger.info("ftp---Session created.");  
	            sshSession.setPassword(ftpServerInfo.getPassword());  
	            Properties properties = new Properties();  
	            properties.put("StrictHostKeyChecking", "no");  
	            sshSession.setConfig(properties);  
	            sshSession.connect();  
	            logger.info("ftp---Session connected.");  
	            Channel channel = sshSession.openChannel("sftp");  
	            channel.connect();  
	            logger.info("Opening Channel.");  
	            sftp = (ChannelSftp) channel;  
	            logger.info("ftp---Connected to " + ftpServerInfo.getIp());  
	        }  
	        catch (Exception e) {  
	        	logger.error(e.getMessage(),e);
	        }  
	        return sftp;  
	}
	
	
	/**
	 * 递归获取指定的文件目录
	 * @param ftpPath
	 * @param fileDirectoryList
	 * @return
	 */
	public R readFTPFileDirectory(String ftpDirectory, List<String> fileDirectoryList, ChannelSftp sftp, List<FtpFileInfo> ftpFileList) {
		logger.info("递归文件目录：" + ftpDirectory);

		try {
			SftpATTRS sftpATTRS = sftp.lstat(ftpDirectory);
			if(!sftpATTRS.isDir()) {
				logger.info("文件目录：" + ftpDirectory + "不存在");
				return R.error("文件目录：" + ftpDirectory + "不存在");
			}
			sftp.cd(ftpDirectory);
			Vector v = sftp.ls(ftpDirectory);
			if (v.size() > 0) {
				Iterator it = v.iterator();
				while (it.hasNext()) {
					LsEntry entry = (LsEntry) it.next();
					if(".".equals(entry.getFilename())||"..".equals(entry.getFilename())){
						continue;
					}
					if (!entry.getAttrs().isDir()) {
						fileDirectoryList.add(ftpDirectory + entry.getFilename());
						FtpFileInfo ftpFileInfo = new FtpFileInfo();
						ftpFileInfo.setFtpPath(ftpDirectory + entry.getFilename());
						FTPFile file = new FTPFile();
						file.setName(entry.getFilename());
						file.setSize(entry.getAttrs().getSize());
						Calendar date = Calendar.getInstance();
						date.setTimeInMillis(Long.valueOf(entry.getAttrs().getMTime()*1000l));
						file.setTimestamp(date);
						ftpFileInfo.setFtpFile(file);
						ftpFileList.add(ftpFileInfo);
					} else if (entry.getAttrs().isDir()) {
						readFTPFileDirectory(ftpDirectory + entry.getFilename() + "/", fileDirectoryList, sftp,
								ftpFileList);
					}
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage(),e);	
			R.error("读取文件异常");
		}
		logger.info("递归读取到文件："+ftpDirectory + " " + fileDirectoryList.size() + fileDirectoryList.toString());
		return R.ok();
	}
	
	
	/**
	 * 下载指定的文件
	 * @param ftpFile
	 * @param ftpPath
	 * @param localPath
	 */
	public R downloadFtpFileByFtpPath(String ftpPath, String localPath,ChannelSftp sftp) throws Exception {
		logger.info("开始下载文件：" + ftpPath);
		SftpATTRS sftpATTRS = sftp.stat(ftpPath);
		if (sftpATTRS == null) {
			logger.info("请求的ftp文件不存在"+ ftpPath);
			return R.error("请求的ftp文件不存在" + ftpPath);
		}
		FTPFile file = new FTPFile();
		file.setName(ftpPath.substring(ftpPath.lastIndexOf("/"), ftpPath.length()));
		file.setSize(sftpATTRS.getSize());
		Calendar date = Calendar.getInstance();
		date.setTimeInMillis(Long.valueOf(sftpATTRS.getMTime()*1000l));
		file.setTimestamp(date);
		String localFileDir = localPath + ftpPath.substring(0, ftpPath.lastIndexOf("/")) + "/";
		String localFile = localPath + ftpPath;
		File localDir = new File(localFileDir);
		if (!localDir.exists()) {
			localDir.mkdirs();
		}
		OutputStream outputStream = null;
		BufferedOutputStream bufferedoutputStream = null;
		try {
			outputStream = new FileOutputStream(localFile); 
			bufferedoutputStream = new BufferedOutputStream(outputStream); 
			//ftp.retrieveFile(ftpPath, outputStream);
			sftp.get(ftpPath, bufferedoutputStream);  
			logger.info("文件下载到" + localFile);
		} catch (Exception e) {
			logger.error(e.getMessage(),e);			
			return R.error("下载文件时失败：" + ftpPath);
		}finally {
			outputStream.close();
			bufferedoutputStream.close();
		}
		return R.ok(file);
	}
	
	public R getFtpFileInfo(String ftpPath,ChannelSftp sftp){
		logger.info("开始获取文件信息：" + ftpPath);
		try {
			if(ftpPath != null) {
				SftpATTRS sftpATTRS = sftp.stat(ftpPath);
				if (sftpATTRS == null) {
					logger.info("请求的ftp文件不存在"+ ftpPath);
					return R.error("请求的ftp文件不存在" + ftpPath);
				}
				FTPFile file = new FTPFile();
				file.setName(ftpPath.substring(ftpPath.lastIndexOf("/")+1, ftpPath.length()));
				file.setSize(sftpATTRS.getSize());
				Calendar date = Calendar.getInstance();
				date.setTimeInMillis(Long.valueOf(sftpATTRS.getMTime()*1000l));
				file.setTimestamp(date);
				return R.ok(file);
			}else {
				return R.error();
			}
		} catch (Exception e) {
			logger.info("开始获取文件信息 异常 " + ftpPath);
			logger.error(e.getMessage(), e);
			return R.error();
		}
		
	}
	
	/**
	 * 上传指定的文件
	 * @param ftpDirectory
	 * @param localPath
	 * @param ftp
	 * @return
	 */
	public R uploadFile(String ftpDirectory,String localPath,FTPClient ftp) {
		logger.info("上传文件开始：localPath->" + localPath +" ftpDirectory->"+ftpDirectory );
		FileInputStream input = null;
		try {
			if(ftp.changeWorkingDirectory(ftpDirectory)) {
				logger.info("文件目录：" + ftpDirectory + "已存在");
			}else {
				logger.info("文件目录：" + ftpDirectory + "不存在,进行创建");
				ftp.makeDirectory(ftpDirectory);
				ftp.changeWorkingDirectory(ftpDirectory);
			}
			input =new FileInputStream(new File(localPath));
			boolean ftpUploadFlag = ftp.storeFile(getFileNamebyFtpPath(localPath), input);
			if(ftpUploadFlag) {
				logger.info("文件上传成功：" + localPath);
				return R.ok();
			}else {
				logger.info("文件上传失败：" + localPath);
				return R.error();
			}
		} catch (Exception e) {
			logger.error("文件上传失败：" + localPath + e.getMessage(),e);
		}finally {
			try {
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		logger.info("上传文件结束：localPath->" + localPath +" ftpDirectory->"+ftpDirectory );
		return R.ok();
		
	}
	
	/**
	 * 关闭连接
	 * @param ftp
	 */
	public void closeSFTPConnection(ChannelSftp sftp) {
		logger.info("关闭FTP连接");
		
		        if (sftp != null) {  
		            if (sftp.isConnected()) {  
		                sftp.disconnect();  
		                sftp = null;  
		                logger.info("sftp is closed already");  
		            }  
		        }  
		       /* if (this.sshSession != null) {  
		            if (this.sshSession.isConnected()) {  
		                this.sshSession.disconnect();  
		                this.sshSession = null;  
		                log.info("sshSession is closed already");  
		            }  
		        }  */
		     
		logger.info("成功关闭FTP连接");
	}
	
	public String getFileNamebyFtpPath(String ftpPath) {
		if(ftpPath != null) {
			ftpPath = ftpPath.replace("\\", "/");
		}
		return  ftpPath.substring(ftpPath.lastIndexOf("/")+1,ftpPath.length());
	}
	
	/**
	 * 反斜线转为斜线
	 * @param backslash
	 * @return
	 */
	public String backslashToforwardslash(String backslash) {
		if(backslash != null && backslash.indexOf("\\") != -1) {
			backslash = backslash.replace("\\", "/");
		}
		return backslash;
	}
}
